﻿using System.Reflection;
using System.Transactions;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using NiuX.Domain.Attributes;
using NiuX.Domain.Repositories;

namespace NiuX.AspNetCore.Infrastructure.Filters;

public class UnitOfWorkFilter : IAsyncActionFilter
{
    private static UnitOfWorkAttribute? GetUoWAttrbute(ActionDescriptor actionDescriptor)
    {
        if (actionDescriptor is not ControllerActionDescriptor controllerActionDescriptor)
        {
            return null;
        }

        var uowAttribute = controllerActionDescriptor.ControllerTypeInfo.GetCustomAttribute<UnitOfWorkAttribute>();
        return uowAttribute ?? controllerActionDescriptor.MethodInfo.GetCustomAttribute<UnitOfWorkAttribute>();
    }
    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        var uowAttr = GetUoWAttrbute(context.ActionDescriptor);

        if (uowAttr == null)
        {
            await next();
            return;
        }

        using TransactionScope transactionScope = new(TransactionScopeAsyncFlowOption.Enabled);

        var result = await next();

        if (result.Exception == null)
        {
            if (uowAttr.DbContextTypes.Any())
            {
                // 用HttpContext的RequestServices，确保获取的是和请求相关的Scope实例
                foreach (var dbCtx in uowAttr.DbContextTypes.Select(dbCtxType => (IUnitOfWork)context.HttpContext.RequestServices.GetRequiredService(dbCtxType)))
                {
                    await dbCtx.SaveChangesAsync();
                }

            }
            else
            {
                foreach (var uow in context.HttpContext.RequestServices.GetServices<IUnitOfWork>())
                {
                    await uow.SaveChangesAsync();
                }
            }


            // 改成 Task.WhenAll 不知道行不行
            transactionScope.Complete();
        }
    }
}
